package com.personal.dataconvert;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.personal.core.data.DataColumn;
import com.personal.core.data.DataRow;
import com.personal.core.data.DataTable;
import com.personal.core.utils.CoreUtil;
import com.personal.core.utils.JsonUtil;
import com.personal.dataconvert.bean.HeaderConfig;
import com.personal.dataconvert.bean.HtmlConfig;
import com.personal.dataconvert.port.Data2DataGrid;
import com.personal.dataconvert.util.ExcelHtmlUtil;

/**
 * DataTable 转UAP的 TreeListView 树表
 * 依赖dataRow中包括ID_COL和PARENTID_COL
 * @author cuibo
 */
public class DataTable2DataGrid_TreeListView implements Data2DataGrid
{
    
    public static final String DATAROW_ID = "DATAROW_ID";
    public static final String DATAROW_PARENTID = "DATAROW_PARENTID";
    public static final String DATAROW_EXPAND = "DATAROW_EXPAND";
    private static final String DATAROW_CHILDLIST = "DATAROW_CHILDLIST";
    
    /** 报表数据 */
    private DataTable table;

    /** splitFlag 表头分割标记。默认是点 */
    private String splitFlag = ".";
    
    /** 2017 06 02 新增手动注入HtmlConfig */
    private HtmlConfig htmlConfig;
    
    /** 是否展开 */
    private boolean expand;


    private DataTable2DataGrid_TreeListView()
    {
    }

    private DataTable2DataGrid_TreeListView(Builder builder)
    {
        this.table = builder.table;
        this.splitFlag = builder.splitFlag;
        this.htmlConfig = builder.htmlConfig;
        this.expand = builder.expand;
        createHtmlConfig();
    }
    
    /**
     * 构建HtmlConfig
     * @return
     * @throws Exception
     */
    private void createHtmlConfig()
    {
        if (htmlConfig != null)
        {
            return;
        }
        htmlConfig = new HtmlConfig();
        htmlConfig.setName(table.getTableName());
        List<HeaderConfig> headerConfigs = null;
        try
        {
            headerConfigs = ExcelHtmlUtil.createTrees(table, splitFlag);
        } catch (Exception e)
        {
        }
        if (CoreUtil.isEmpty(headerConfigs))
        {
            throw new IllegalArgumentException("datatable信息不合法，创建表头配置失败！");
        }
        htmlConfig.setTableClass(CoreUtil.parseStr(table.getTag()));
        htmlConfig.setHeaderConfigs(headerConfigs);
    }

    
    @Override
    public String createColums() throws Exception
    {
        if (CoreUtil.isEmpty(htmlConfig.getHeaderConfigs()))
        {
            return "[]";
        }
        List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
        for (HeaderConfig config : htmlConfig.getHeaderConfigs())
        {
            list.add(headerConfig2Map(config));
        }
        return JsonUtil.toJson(list);
    }
    
    /**
     * HeaderConfig转Map
     * @param config
     * @return
     */
    private Map<String, Object> headerConfig2Map(HeaderConfig config)
    {
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        headerConfig2MapImpl(result, config);
        return result;
    }
    
    private void headerConfig2MapImpl(Map<String, Object> result, HeaderConfig config)
    {
        result.put("name", config.getValue());
        result.put("text", config.getDisplayName());
        result.put("width", config.getWidth() + "");
        result.put("align", CoreUtil.isEmpty(config.getAlign()) ? HeaderConfig.CENTER : config.getAlign());
        if (config.getWidth() <= 0 )
        {
            result.put("visible", "false");
        }
        if (!CoreUtil.isEmpty(config.getChildren()))
        {
            List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
            for (HeaderConfig child : config.getChildren())
            {
                Map<String, Object> childMap = new LinkedHashMap<String, Object>();
                headerConfig2MapImpl(childMap, child);
                list.add(childMap);
                result.put("columns", list);
            }
        }
    }
    
//    @Override
//    public String createColums() throws Exception
//    {
//        if (CoreUtil.isEmpty(htmlConfig.getHeaderConfigs()))
//        {
//            return "[]";
//        }
//        StringBuilder result = new StringBuilder();
//        result.append("[\n");
//        int colIndex = -1;
//        for (HeaderConfig config : htmlConfig.getHeaderConfigs())
//        {
//            colIndex ++;
//            result.append(headerConfig2Json(config));
//            if (colIndex != htmlConfig.getHeaderConfigs().size() - 1)
//            {
//                result.append(",");
//            }
//            result.append("\n");
//        }
//        result.append("]");
//        return result.toString();
//    }
    
//    [
//     { name: "name", text: "名称" },
//     { name: "value", text: "值" }
//    ], 
    @SuppressWarnings("unused")
    private String headerConfig2Json(HeaderConfig config)
    {
        StringBuilder result = new StringBuilder();
        headerConfig2JsonImpl(result, config);
        return result.toString();
    }

    private void headerConfig2JsonImpl(StringBuilder result, HeaderConfig config)
    {
        result.append("{ \"name\":\"").append(config.getValue()).append("\", \"text\":\"").append(config.getDisplayName())
            .append("\", \"width\":\"").append(config.getWidth()).append("\", \"align\":\"").append(CoreUtil.isEmpty(config.getAlign()) ? HeaderConfig.CENTER : config.getAlign())
            .append("\" ");
        // 如果宽度小于等于0，则设置为不可见
        if (config.getWidth() <= 0 )
        {
            result.append(", \"visible\":false ");
        }
        
        if (!CoreUtil.isEmpty(config.getChildren()))
        {
            result.append(", \"columns\":[\n ");
            for (HeaderConfig child : config.getChildren())
            {
                headerConfig2JsonImpl(result, child);
            }
            result.append("\n] ");
        }
        result.append(" }");
    }
    
    @Override
    public String createRows() throws Exception
    {
        if (!CoreUtil.checkDataTableHasData(table))
        {
            return "[]";
        }
        Map<String, List<DataRow>> cacheMap = new HashMap<String, List<DataRow>>();
        List<DataRow> firstLevel = new ArrayList<DataRow>();
        for (DataRow row : table.getRows())
        {
            String parentId = CoreUtil.parseStr(row.getItemMap().get(DATAROW_PARENTID));
            if (CoreUtil.isEmpty(parentId))
            {
                firstLevel.add(row);
                continue;
            }
            List<DataRow> list = cacheMap.get(parentId);
            if (list == null)
            {
                list = new ArrayList<DataRow>();
                cacheMap.put(parentId, list);
            }
            list.add(row);
        }
        List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
        for (DataRow row : firstLevel)
        {
            row.getItemMap().put(DATAROW_CHILDLIST, cacheMap.get(CoreUtil.parseStr(row.getItemMap().get(DATAROW_ID))));
            list.add(dataRow2Map(table, row));
        }
        return JsonUtil.toJson(list);
    }
    

//    @Override
//    public String createRows() throws Exception
//    {
//        if (!CoreUtil.checkDataTableHasData(table))
//        {
//            return "[]";
//        }
//        Map<String, List<DataRow>> cacheMap = new HashMap<String, List<DataRow>>();
//        List<DataRow> firstLevel = new ArrayList<DataRow>();
//        for (DataRow row : table.getRows())
//        {
//            String parentId = CoreUtil.parseStr(row.getItemMap().get(DATAROW_PARENTID));
//            if (CoreUtil.isEmpty(parentId))
//            {
//                firstLevel.add(row);
//                continue;
//            }
//            List<DataRow> list = cacheMap.get(parentId);
//            if (list == null)
//            {
//                list = new ArrayList<DataRow>();
//                cacheMap.put(parentId, list);
//            }
//            list.add(row);
//        }
//        StringBuilder result = new StringBuilder();
//        result.append("[\n ");
//        int rowIndex = -1;
//        for (DataRow row : firstLevel)
//        {
//            row.getItemMap().put(DATAROW_CHILDLIST, cacheMap.get(CoreUtil.parseStr(row.getItemMap().get(DATAROW_ID))));
//            rowIndex ++;
//            result.append(dataRow2Json(row));
//            if (rowIndex != firstLevel.size() - 1)
//            {
//                result.append(",");
//            }
//            result.append("\n");
//        }
//        result.append("]");
//        return result.toString();
//    }
//    
    /**
     * Datarow转Map
     * @param config
     * @return
     */
    private Map<String, Object> dataRow2Map(DataTable table, DataRow row)
    {
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        dataRow2MapImpl(result, table, row);
        return result;
    }
    
    private void dataRow2MapImpl(Map<String, Object> result, DataTable table, DataRow row)
    {
        for (DataColumn column : table.getColumns())
        {
            result.put(column.getColumnName(), row.getItemMap().get(column.getColumnName()));
        }
        @SuppressWarnings("unchecked")
        List<DataRow> children = (List<DataRow>) row.getItemMap().get(DATAROW_CHILDLIST);
        if (!CoreUtil.isEmpty(children))
        {
            boolean expand = row.getItemMap().get(DATAROW_EXPAND) == null ? this.expand : CoreUtil.parseBoolean(row.getItemMap().get(DATAROW_EXPAND));
            result.put("itemType", "folder");
            result.put("expanded", expand);
            result.put("hasChildren", true);
            List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
            for (DataRow child : children)
            {
                list.add(dataRow2Map(table, child));
            }
            result.put("items", list);
        } else
        {
            result.put("itemType", "role");
            result.put("hasChildren", false);
        }
    }
    
    @SuppressWarnings("unused")
    private String dataRow2Json(DataRow row)
    {
        StringBuilder result = new StringBuilder();
        dataRow2JsonImpl(result, row);
        return result.toString();
    }
    
    private void dataRow2JsonImpl(StringBuilder result, DataRow row)
    {
        result.append("{ ");
        for (DataColumn column : table.getColumns())
        {
            result.append("\"").append(column.getColumnName()).append("\":\"").append(CoreUtil.parseStr(row.getItemMap().get(column.getColumnName()))).append("\",\n");
        }
        @SuppressWarnings("unchecked")
        List<DataRow> children = (List<DataRow>) row.getItemMap().get(DATAROW_CHILDLIST);
        if (!CoreUtil.isEmpty(children))
        {
            boolean expand = row.getItemMap().get(DATAROW_EXPAND) == null ? this.expand : CoreUtil.parseBoolean(row.getItemMap().get(DATAROW_EXPAND));
            result.append("\"itemType\":\"folder\"").append(",\n");
            result.append("\"expanded\":").append(expand).append(",\n");
            result.append("\"hasChildren\":true").append(",\n");
            result.append("\"items\":[\n ");
            int rowIndex = -1;
            for (DataRow dataRow : children)
            {
                rowIndex ++;
                dataRow2JsonImpl(result, dataRow);
                if (rowIndex != children.size() - 1)
                {
                    result.append(",\n");
                } 
            }
            result.append("] \n");
        } else
        {
            result.append("\"itemType\":\"role\" ,\n");
            result.append("\"hasChildren\":false").append("\n");
        }
        result.append("}");
    }
    

    /**
     * 建造
     * @author cuibo
     */
    public static class Builder
    {
        private DataTable table;
        private String splitFlag = ".";
        private HtmlConfig htmlConfig;
        private boolean expand = true;

        public Builder setDataTable(DataTable table)
        {
            this.table = table;
            return this;
        }

        public Builder setSplitFlag(String splitFlag)
        {
            this.splitFlag = splitFlag;
            return this;
        }

        public Builder setHtmlConfig(HtmlConfig htmlConfig)
        {
            this.htmlConfig = htmlConfig;
            return this;
        }
        
        public Builder setExpand(boolean expand)
        {
            this.expand = expand;
            return this;
        }

        public DataTable2DataGrid_TreeListView build()
        {
            return new DataTable2DataGrid_TreeListView(this);
        }
    }


}
